home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / Papers / Garrison / Code / SchmoozingExamples / IterativeServer.m < prev    next >
Encoding:
Text File  |  2001-06-23  |  5.2 KB  |  149 lines

  1. //
  2. //  IterativeServer.m
  3. //  SchmoozingExamples
  4. //
  5. //  Created by garrison on Fri Apr 20 2001.
  6. //  Copyright (c) 2001 Standard Orbit Software, LLC. All rights reserved.
  7. //
  8. //  Permission is granted to use this code for any purpose, at your own risk.
  9. //  No warranties are expressed or implied.
  10. //
  11.  
  12. /* An Algorithm for an Iterative Server [Comer93]
  13. 1) Create a socket and bind it to a well known port number for the server being offered.
  14. 2) Establish a listener on the socket for incoming connections.
  15. 3) Accept the next connection request on the socket and obtain a new socket for the connection.
  16. 4) Repeatedly read the socket for a client request, generate a response, and send the reply back according to the application’s protocol.
  17. 5) When finished handling a particular client request, close the connection and go back to step 3, accepting the next connection.
  18. */
  19.  
  20. #import <Foundation/Foundation.h>
  21. #import <OmniNetworking/OmniNetworking.h>
  22. #import "Connection.h"
  23. #import "IterativeServer.h"
  24.  
  25. @implementation IterativeServer
  26.  
  27.  - (void) run
  28.  {
  29.     // Implement an iterative connection processing strategy, as defined
  30.     // by Comer's InterNetworking with TCP/IP, Vol III.  The server accepts 
  31.     // a new connection, processes it, then closes the connection before handling 
  32.     // the next one.  Requests will queue up on the listening socket up to the
  33.     // the limit defined by the OS.  Darwin permits up to 128 unaccepted connection
  34.     // requests (according to the /usr/include/sys/socket.h header).
  35.     
  36.     ONTCPSocket *connectionSocket = nil;
  37.     Connection *someClient = nil;
  38.     unsigned short connectionCount = 0;
  39.     
  40.     // connectionSocket holds a reference to the accepted connection.
  41.     
  42.     // someClient is an instance of our custom connection handling class.
  43.     
  44.     // connectionCount holds a count of connections accepted to
  45.     // provide some feedback in the spartan console UI.
  46.     
  47.     
  48.     // The server starts here.
  49.     NSLog(@"Iterative Server");
  50.     
  51.     do {
  52.         NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
  53.         // Create an autorelease pool to contain memory use in the loop.
  54.             
  55.         NS_DURING 
  56.         {
  57.             NSLog(@"Listening for the next connection");
  58.             
  59.             connectionSocket = [listeningSocket acceptConnectionOnNewSocket];
  60.             // Step 3.  Accept the next incoming connection.  Server execution
  61.             // will block until a connection request is received.
  62.             
  63.             connectionCount += 1;
  64.             // Increment the accepted connection count
  65.  
  66.             NSLog(@"Accepted connection %d from host %@", connectionCount, 
  67.                         [[connectionSocket remoteAddressHost] hostname]);
  68.             // Some console feedback
  69.                        
  70.             someClient = [[Connection alloc] initWithConnectedSocket:connectionSocket];
  71.             // Create a connection object with the.
  72.             
  73.             [someClient processConnection];
  74.             // Step 4. Process the connection in a server-specific way.
  75.             
  76.             NSLog(@"Processed connection %d.", connectionCount);
  77.             // Process the connection.  This routine must return before the server
  78.             // can accept and process any subsequent connections.
  79.             
  80.             [someClient release];
  81.             // Step 5. Close the connection and go on to the next one.
  82.         
  83.             [loopPool release];
  84.         }
  85.         NS_HANDLER 
  86.         {
  87.             NSLog(@"Exception %@ raised during server processing: %@", 
  88.                 [localException name], localException);
  89.             
  90.             [loopPool release];
  91.             
  92.             break;
  93.             // Close done the server loop if an error occurs.
  94.         }
  95.         NS_ENDHANDLER
  96.         
  97.                 
  98.     } while (1);
  99.     // This server loops forever, accepting new connections.  As implemented here, 
  100.     // the only way the server will stop operating is if an exception is raised 
  101.     // during execution.  You would want to add some additional means of gracefully
  102.     // bringing a server down (e.g. handling a SIGKILL or SIGHUP signal). 
  103.     
  104.  }
  105.  
  106.  
  107.  
  108.  
  109. - (id) initWithLocalPort:(unsigned short) aPort
  110. {
  111.     self = [super init];
  112.     
  113.     if ( self )
  114.     {
  115.         NS_DURING {
  116.             listeningSocket = [[ONTCPSocket tcpSocket] retain];
  117.             // Step 1. Create an ONTCPSocket for the server.
  118.             
  119.             [listeningSocket startListeningOnLocalPort:aPort allowingAddressReuse:YES];
  120.             // Step 2. Start socket listening on the server's well known port.  Allowing 
  121.             // address reuse is helpful while debugging (it prevents a port from getting 
  122.             // locked up if your app crashes or you terminate execution in gdb without 
  123.             // closing the socket).
  124.             
  125.             NSLog(@"Listening for connections on host %@:%d", [ONHost localHostname], aPort);
  126.         }
  127.         NS_HANDLER {
  128.             // Handle potential exceptions.
  129.             NSLog(@"Server init raised %@ (%@)", [localException name], localException);
  130.             [listeningSocket release];
  131.             return nil;
  132.         }
  133.         NS_ENDHANDLER
  134.     }
  135.     
  136.     return self;
  137. }
  138.  
  139.  
  140. - (void) dealloc
  141. {
  142.     [listeningSocket release];
  143.     
  144.     [super dealloc];
  145. }
  146.  
  147.  
  148. @end
  149.